using Project.ViewModels;
using Project.Views.Abstractions;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace Project.Views
{
    [RequireComponent(typeof(CanvasGroup))]
    public class CharacterStatsPanelView : DisposableViewBase
    {
        private CharacterStatsPanelViewModel _characterViewModel;
        private CanvasGroup _canvasGroup;

        [SerializeField] private TMP_Text _nameText;
        [SerializeField] private TMP_Text _pointsToSpendText;
        [SerializeField] private Image _image;
        [Space]
        [SerializeField] private TMP_Text _strengthPointsText;
        [SerializeField] private TMP_Text _agilityPointsText;
        [SerializeField] private TMP_Text _intelligencePointsText;
        [Space]
        [SerializeField] private TMP_Text _healthPointsText;
        [SerializeField] private TMP_Text _armorPointsText;
        [SerializeField] private TMP_Text _manaPointsText;
        [Space]
        [SerializeField] private TMP_Text _maxHealthPointsText;
        [SerializeField] private TMP_Text _maxArmorPointsText;
        [SerializeField] private TMP_Text _maxManaPointsText;
        [Space]
        [SerializeField] private Button _increaseStrengthPointsButton;
        [SerializeField] private Button _increaseAgilityPointsButton;
        [SerializeField] private Button _increaseIntelligencePointsButton;
        [Space]
        [SerializeField] private Button _decreaseStrengthPointsButton;
        [SerializeField] private Button _decreaseAgilityPointsButton;
        [SerializeField] private Button _decreaseIntelligencePointsButton;
        [Space]
        [SerializeField] private Slider _healthPointsSlider;
        [SerializeField] private Slider _armorPointsSlider;
        [SerializeField] private Slider _manaPointsSlider;

        public void Initialize(CharacterStatsPanelViewModel characterViewModel)
        {
            _canvasGroup = this.GetComponent<CanvasGroup>();
            _characterViewModel = characterViewModel;

            Subscribe();
            UpdateValues();
        }

        public void Show()
        {
            _canvasGroup.alpha = 1;
            _canvasGroup.blocksRaycasts = true;
        }

        public void Hide()
        {
            _canvasGroup.alpha = 0;
            _canvasGroup.blocksRaycasts = false;
        }

        public void SetViewModel(CharacterStatsPanelViewModel characterViewModel)
        {
            if (characterViewModel != null)
            {
                Unsubscribe();

                _characterViewModel = characterViewModel;

                Subscribe();
                UpdateValues();
            }
        }

        private void UpdateValues()
        {
            OnNameValueChanged(_characterViewModel.Name.Value);
            OnSpriteValueChanged(_characterViewModel.Sprite.Value);

            OnPointsToSpendValueChanged(_characterViewModel.PointsToSpend.Value);

            OnStrengthPointsValueChanged(_characterViewModel.StrengthPoints.Value);
            OnAgilityPointsValueChanged(_characterViewModel.AgilityPoints.Value);
            OnIntelligencePointsValueChanged(_characterViewModel.IntelligencePoints.Value);

            OnHealthPointsValueChanged(_characterViewModel.HealthPoints.Value);
            OnArmorPointsValueChanged(_characterViewModel.ArmorPoints.Value);
            OnManaPointsValueChanged(_characterViewModel.ManaPoints.Value);

            OnHealthPointsMaxValueChanged(_characterViewModel.HealthPoints.MaxValue);
            OnArmorPointsMaxValueChanged(_characterViewModel.ArmorPoints.MaxValue);
            OnManaPointsMaxValueChanged(_characterViewModel.ManaPoints.MaxValue);

            OnCanIncreaseStrengthPointsValueChanged(_characterViewModel.CanIncreaseStrengthPoints.Value);
            OnCanIncreaseAgilityPointsValueChanged(_characterViewModel.CanIncreaseAgilityPoints.Value);
            OnCanIncreaseIntelligencePointsValueChanged(_characterViewModel.CanIncreaseIntelligencePoints.Value);

            OnCanDecreaseStrengthPointsValueChanged(_characterViewModel.CanDecreaseStrengthPoints.Value);
            OnCanDecreaseAgilityPointsValueChanged(_characterViewModel.CanDecreaseAgilityPoints.Value);
            OnCanDecreaseIntelligencePointsValueChanged(_characterViewModel.CanDecreaseIntelligencePoints.Value);
        }
        protected override void Subscribe()
        {
            _characterViewModel.Name.ValueChanged += OnNameValueChanged;
            _characterViewModel.Sprite.ValueChanged += OnSpriteValueChanged;

            _characterViewModel.PointsToSpend.ValueChanged += OnPointsToSpendValueChanged;

            _characterViewModel.StrengthPoints.ValueChanged += OnStrengthPointsValueChanged;
            _characterViewModel.AgilityPoints.ValueChanged += OnAgilityPointsValueChanged;
            _characterViewModel.IntelligencePoints.ValueChanged += OnIntelligencePointsValueChanged;

            _characterViewModel.HealthPoints.ValueChanged += OnHealthPointsValueChanged;
            _characterViewModel.ArmorPoints.ValueChanged += OnArmorPointsValueChanged;
            _characterViewModel.ManaPoints.ValueChanged += OnManaPointsValueChanged;

            _characterViewModel.HealthPoints.MaxValueChanged += OnHealthPointsMaxValueChanged;
            _characterViewModel.ArmorPoints.MaxValueChanged += OnArmorPointsMaxValueChanged;
            _characterViewModel.ManaPoints.MaxValueChanged += OnManaPointsMaxValueChanged;

            _characterViewModel.CanIncreaseStrengthPoints.ValueChanged += OnCanIncreaseStrengthPointsValueChanged;
            _characterViewModel.CanIncreaseAgilityPoints.ValueChanged += OnCanIncreaseAgilityPointsValueChanged;
            _characterViewModel.CanIncreaseIntelligencePoints.ValueChanged += OnCanIncreaseIntelligencePointsValueChanged;

            _characterViewModel.CanDecreaseStrengthPoints.ValueChanged += OnCanDecreaseStrengthPointsValueChanged;
            _characterViewModel.CanDecreaseAgilityPoints.ValueChanged += OnCanDecreaseAgilityPointsValueChanged;
            _characterViewModel.CanDecreaseIntelligencePoints.ValueChanged += OnCanDecreaseIntelligencePointsValueChanged;

            _increaseStrengthPointsButton.onClick.AddListener(OnIncreaseStrengthPointsButtonClicked);
            _increaseAgilityPointsButton.onClick.AddListener(OnIncreaseAgilityPointsButtonClicked);
            _increaseIntelligencePointsButton.onClick.AddListener(OnIncreaseIntelligencePointsButtonClicked);

            _decreaseStrengthPointsButton.onClick.AddListener(OnDecreaseStrengthPointsButtonClicked);
            _decreaseAgilityPointsButton.onClick.AddListener(OnDecreaseAgilityPointsButtonClicked);
            _decreaseIntelligencePointsButton.onClick.AddListener(OnDecreaseIntelligencePointsButtonClicked);
        }
        protected override void Unsubscribe()
        {
            _characterViewModel.Name.ValueChanged -= OnNameValueChanged;
            _characterViewModel.Sprite.ValueChanged -= OnSpriteValueChanged;

            _characterViewModel.PointsToSpend.ValueChanged -= OnPointsToSpendValueChanged;

            _characterViewModel.StrengthPoints.ValueChanged -= OnStrengthPointsValueChanged;
            _characterViewModel.AgilityPoints.ValueChanged -= OnAgilityPointsValueChanged;
            _characterViewModel.IntelligencePoints.ValueChanged -= OnIntelligencePointsValueChanged;

            _characterViewModel.HealthPoints.ValueChanged -= OnHealthPointsValueChanged;
            _characterViewModel.ArmorPoints.ValueChanged -= OnArmorPointsValueChanged;
            _characterViewModel.ManaPoints.ValueChanged -= OnManaPointsValueChanged;

            _characterViewModel.HealthPoints.MaxValueChanged -= OnHealthPointsMaxValueChanged;
            _characterViewModel.ArmorPoints.MaxValueChanged -= OnArmorPointsMaxValueChanged;
            _characterViewModel.ManaPoints.MaxValueChanged -= OnManaPointsMaxValueChanged;

            _characterViewModel.CanIncreaseStrengthPoints.ValueChanged -= OnCanIncreaseStrengthPointsValueChanged;
            _characterViewModel.CanIncreaseAgilityPoints.ValueChanged -= OnCanIncreaseAgilityPointsValueChanged;
            _characterViewModel.CanIncreaseIntelligencePoints.ValueChanged -= OnCanIncreaseIntelligencePointsValueChanged;

            _characterViewModel.CanDecreaseStrengthPoints.ValueChanged -= OnCanDecreaseStrengthPointsValueChanged;
            _characterViewModel.CanDecreaseAgilityPoints.ValueChanged -= OnCanDecreaseAgilityPointsValueChanged;
            _characterViewModel.CanDecreaseIntelligencePoints.ValueChanged -= OnCanDecreaseIntelligencePointsValueChanged;

            _increaseStrengthPointsButton.onClick.RemoveListener(OnIncreaseStrengthPointsButtonClicked);
            _increaseAgilityPointsButton.onClick.RemoveListener(OnIncreaseAgilityPointsButtonClicked);
            _increaseIntelligencePointsButton.onClick.RemoveListener(OnIncreaseIntelligencePointsButtonClicked);

            _decreaseStrengthPointsButton.onClick.RemoveListener(OnDecreaseStrengthPointsButtonClicked);
            _decreaseAgilityPointsButton.onClick.RemoveListener(OnDecreaseAgilityPointsButtonClicked);
            _decreaseIntelligencePointsButton.onClick.RemoveListener(OnDecreaseIntelligencePointsButtonClicked);
        }

        private void OnNameValueChanged(string newValue) =>
            _nameText.text = newValue;
        private void OnSpriteValueChanged(Sprite newValue) =>
            _image.sprite = newValue;

        private void OnPointsToSpendValueChanged(int newValue) => 
            _pointsToSpendText.text = newValue.ToString();

        private void OnStrengthPointsValueChanged(int newValue) =>
            _strengthPointsText.text = newValue.ToString();
        private void OnAgilityPointsValueChanged(int newValue) =>
            _agilityPointsText.text = newValue.ToString();
        private void OnIntelligencePointsValueChanged(int newValue) =>
            _intelligencePointsText.text = newValue.ToString();

        private void OnHealthPointsValueChanged(int newValue) 
        {
            _healthPointsText.text = newValue.ToString();
            _healthPointsSlider.value = newValue;
        }
        private void OnArmorPointsValueChanged(int newValue) 
        {
            _armorPointsText.text = newValue.ToString();
            _armorPointsSlider.value = newValue;
        }
        private void OnManaPointsValueChanged(int newValue)
        {
            _manaPointsText.text = newValue.ToString();
            _manaPointsSlider.value = newValue;
        }

        private void OnHealthPointsMaxValueChanged(int newValue)
        {
            _maxHealthPointsText.text = newValue.ToString();
            _healthPointsSlider.maxValue = newValue;
        }
        private void OnArmorPointsMaxValueChanged(int newValue)
        {
            _maxArmorPointsText.text= newValue.ToString();
            _armorPointsSlider.maxValue = newValue;
        }
        private void OnManaPointsMaxValueChanged(int newValue)
        {
            _maxManaPointsText.text= newValue.ToString();
            _manaPointsSlider.maxValue = newValue;
        }
        
        private void OnCanIncreaseStrengthPointsValueChanged(bool newValue) =>
            _increaseStrengthPointsButton.interactable = newValue;
        private void OnCanIncreaseAgilityPointsValueChanged(bool newValue) =>
            _increaseAgilityPointsButton.interactable = newValue;
        private void OnCanIncreaseIntelligencePointsValueChanged(bool newValue) =>
            _increaseIntelligencePointsButton.interactable = newValue;

        private void OnCanDecreaseStrengthPointsValueChanged(bool newValue) =>
            _decreaseStrengthPointsButton.interactable = newValue;
        private void OnCanDecreaseAgilityPointsValueChanged(bool newValue) =>
            _decreaseAgilityPointsButton.interactable = newValue;
        private void OnCanDecreaseIntelligencePointsValueChanged(bool newValue) =>
            _decreaseIntelligencePointsButton.interactable = newValue;

        private void OnIncreaseStrengthPointsButtonClicked() =>
            _characterViewModel.IncreaseStrengthPoints();
        private void OnIncreaseAgilityPointsButtonClicked() =>
            _characterViewModel.IncreaseAgilityPoints();
        private void OnIncreaseIntelligencePointsButtonClicked() =>
            _characterViewModel.IncreaseIntelligencePoints();

        private void OnDecreaseStrengthPointsButtonClicked() =>
            _characterViewModel.DecreaseStrengthPoints();
        private void OnDecreaseAgilityPointsButtonClicked() =>
            _characterViewModel.DecreaseAgilityPoints();
        private void OnDecreaseIntelligencePointsButtonClicked() =>
            _characterViewModel.DecreaseIntelligencePoints();
    }
}
